﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Linq;
using System.Reflection;
using NHibernate.Criterion;

namespace JuCloudy.Data.Nhibernate.App
{
    public class AppContainer<TEntity>        where TEntity:class,new()
    {
        private static global::NHibernate.Cfg.Configuration mCfg = null;
        private static global::NHibernate.ISessionFactory SessionFactory = null;
        public AppContainer(String AppSettingKey)
        {
            mCfg = new NHibernate.Cfg.Configuration().Configure(
               System.Web.HttpContext.Current.Server.MapPath(
                    System.Configuration.ConfigurationManager.AppSettings[AppSettingKey]
                    ));

            SessionFactory = null;

            mCfg.AddClass(typeof(TEntity));
            SessionFactory = mCfg.BuildSessionFactory();
        }
        public List<TEntity> Insert(TEntity Entity)
        {
            using (NHibernate.ISession session = SessionFactory.OpenSession())
            {
                using (NHibernate.ITransaction vTransaction = session.BeginTransaction())
                {
                    try
                    {
                        session.SaveOrUpdate(Entity);
                        vTransaction.Commit();
                        var query = session.Query<TEntity>().ToList();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                        return query;
                    }
                    catch (Exception ex)
                    {
                        vTransaction.Rollback();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                        throw ex;
                    }
                }
            }
        }

        public List<TEntity> Delete(TEntity Entity)
        {
            using (ISession session = SessionFactory.OpenSession())
            {
                using (ITransaction vTransaction = session.BeginTransaction())
                {
                    try
                    {
                        session.Delete(Entity);
                        vTransaction.Commit();
                        var query = session.Query<TEntity>().ToList();
                        vTransaction.Dispose(); 
                        session.Flush();
                        session.Close();
                        session.Dispose();
                        return query;
                    }
                    catch (Exception ex)
                    {
                        vTransaction.Rollback();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                        throw ex;
                    }
                }
            }
        }

        public List<TEntity> GetEntities()
        {
            using (ISession session = SessionFactory.OpenSession())
            {
                
                var query = session.Query<TEntity>().ToList();
                session.Flush();
                session.Close();
                session.Dispose();
                return query;
            }
        }

        public TEntity GetEntity(String Field,String Value)
        {
            using (ISession session = SessionFactory.OpenSession())
            {
                IList<TEntity> entity = session.CreateCriteria(typeof(TEntity))
                    .Add(Restrictions.Eq(Field, int.Parse(Value))).List<TEntity>();
                TEntity result = null;
                if(entity.Count>0)
                {
                    result= entity[0];
                    session.Flush();
                    session.Close();
                    session.Dispose();
                    return result;
                }
                else
                {
                    
                    session.Flush();
                    session.Close();
                    session.Dispose();
                    throw new Exception("查询不存在");
                }

                
            }
        }
        public TEntity GetEntitiesWithIC(String Field, ICriterion ic , String Value)
        {
            using (ISession session = SessionFactory.OpenSession())
            {
                var  Criteria= session.CreateCriteria(typeof(TEntity));

                    Criteria.Add(ic);

                var entity = Criteria.List<TEntity>();

                TEntity result = null;
                if (entity.Count > 0)
                {
                    result = entity[0];
                    session.Flush();
                    session.Close();
                    session.Dispose();
                    return result;
                }
                else
                {

                    session.Flush();
                    session.Close();
                    session.Dispose();
                    throw new Exception("查询不存在");
                }


            }
        }
    }



    public class PropertyComparer<T> : IEqualityComparer<T>
    {
        private PropertyInfo _PropertyInfo;

        /// <summary>
        /// 通过propertyName 获取PropertyInfo对象    
        /// </summary>
        /// <param name="propertyName"></param>
        public PropertyComparer(string propertyName)
        {
            _PropertyInfo = typeof(T).GetProperty(propertyName,
            BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);
            if (_PropertyInfo == null)
            {
                throw new ArgumentException(string.Format("{0} is not a property of type {1}.",
                    propertyName, typeof(T)));
            }
        }

        #region IEqualityComparer<T> Members

        public bool Equals(T x, T y)
        {
            object xValue = _PropertyInfo.GetValue(x, null);
            object yValue = _PropertyInfo.GetValue(y, null);

            if (xValue == null)
                return yValue == null;

            return xValue.Equals(yValue);
        }

        public int GetHashCode(T obj)
        {
            object propertyValue = _PropertyInfo.GetValue(obj, null);

            if (propertyValue == null)
                return 0;
            else
                return propertyValue.GetHashCode();
        }

        #endregion
    }
}
